package personnal.jonat;

import static personnal.jonat.ExcelUtils.getOrCreateCell;
import static personnal.jonat.ExcelUtils.setCellNumericValue;
import static personnal.jonat.ExcelUtils.setCellStringValue;
import static personnal.jonat.PropertiesUtils.defaultInt;
import static personnal.jonat.PropertiesUtils.defaultShort;
import static personnal.jonat.PropertiesUtils.defaultString;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class StudentOutComeGenerator {

    private static final Logger logger = Logger.getLogger(StudentOutComeGenerator.class);

    private static final String TEMPLATE_FILE_PATH = "template.xls";
    private static final int DATA_SHEET_INDEX = 0;

    private static final short CLASSNAME_ROW_INDEX = 1;
    private static final short CLASSNAME_COLUMN_INDEX = 0;

    private static final short STUDENTNAME_ROW_INDEX = 2;
    private static final short STUDENTNAME_COLUMN_INDEX = 1;

    private static final short SKILL_ROW_START_INDEX = 4;

    private static final short CLASS_GRADE_COLUMN_INDEX = 2;
    private static final short STUDENT_GRADE_COLUMN_INDEX = 1;
    
    private String templateFilePath = TEMPLATE_FILE_PATH;
    private int dataSheetIndex = DATA_SHEET_INDEX;
    private short classNameRowIndex = CLASSNAME_ROW_INDEX;
    private short classNameColumnIndex = CLASSNAME_COLUMN_INDEX;
    private short studentNameRowIndex = STUDENTNAME_ROW_INDEX;
    private short studentNameColumnIndex = STUDENTNAME_COLUMN_INDEX;
    private short skillRowStartIndex = SKILL_ROW_START_INDEX;
    private short classGradeColumnIndex = CLASS_GRADE_COLUMN_INDEX;
    private short studentGradeColumnIndex = STUDENT_GRADE_COLUMN_INDEX;
    
    public StudentOutComeGenerator(Properties properties) {
		super();
		this.templateFilePath 			= defaultString(properties, "template.path", TEMPLATE_FILE_PATH);
		this.dataSheetIndex 			= defaultInt(properties, "template.sheet.index", DATA_SHEET_INDEX);
		this.classNameRowIndex 			= defaultShort(properties, "template.className.rowIndex", CLASSNAME_ROW_INDEX);
		this.classNameColumnIndex 		= defaultShort(properties, "template.className.columnIndex", CLASSNAME_COLUMN_INDEX);
		this.studentNameRowIndex 		= defaultShort(properties, "template.studentName.rowIndex", STUDENTNAME_ROW_INDEX);
		this.studentNameColumnIndex 	= defaultShort(properties, "template.studentName.columnIndex", STUDENTNAME_COLUMN_INDEX);
		this.skillRowStartIndex 		= defaultShort(properties, "template.skillRow.startIndex", SKILL_ROW_START_INDEX);
		this.classGradeColumnIndex 		= defaultShort(properties, "template.classGrade.columnIndex", CLASS_GRADE_COLUMN_INDEX);
		this.studentGradeColumnIndex 	= defaultShort(properties, "template.studentGrade.columnIndex", STUDENT_GRADE_COLUMN_INDEX);
	}

	public StudentOutComeGenerator() {
		super();
	}

	public void generateOutcomes(OutCome outCome, File outputDirectory) throws IOException {
        validateOutputDirectory(outputDirectory);
        File templateFile = new File(templateFilePath);
        logger.debug("Using Excel template file from: " + templateFile.getAbsolutePath());
        InputStream inputStream = new FileInputStream(templateFile);
        try {
            HSSFWorkbook templateWorkbook = new HSSFWorkbook(inputStream);
            for (Student student : outCome.getStudents()) {
                fillWorkbookForStudent(templateWorkbook, outCome.getTitle(), student);
                generateFileForStudent(outputDirectory, templateWorkbook, student);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    protected void validateOutputDirectory(File outputDirectory) throws IOException {
        if (outputDirectory.exists() == false) {
            boolean createSuccessfull = outputDirectory.mkdirs();
            if (createSuccessfull == false) {
                throw new IOException("Can't create output directory: " + outputDirectory.getPath());
            }
        } else if (outputDirectory.isDirectory() == false) {
            throw new IOException("Output directory point to a file not a directory: " + outputDirectory.getPath());
        }
    }

    protected void fillWorkbookForStudent(HSSFWorkbook templateWorkbook, String title, Student student) {
        logger.debug("Filling workbook for student: " + student.getName());
        HSSFSheet templateSheet = templateWorkbook.getSheetAt(dataSheetIndex);
        // Ajout du nom de la classe
        if (title != null) {
	        HSSFCell titleCell = getOrCreateCell(templateSheet, classNameRowIndex, classNameColumnIndex);
	        setCellStringValue(titleCell, title);
        }
        // Ajout du nom de l'élève
        HSSFCell nameCell = getOrCreateCell(templateSheet, studentNameRowIndex, studentNameColumnIndex);
        setCellStringValue(nameCell, student.getName() + " : " + student.getAverageGrade());
        // Ajout des moyennes
        fillGrades(student.getClassGrades(), templateSheet, classGradeColumnIndex);
        // Ajout des notes de l'élève
        fillGrades(student.getGrades(), templateSheet, studentGradeColumnIndex);
    }

    protected void generateFileForStudent(File outputDirectory, HSSFWorkbook templateWorkbook, Student student)
            throws FileNotFoundException, IOException {
        File outputFile = new File(outputDirectory, student.getName() + ".xls");
        logger.debug("Writing workbook to: " + outputFile.getPath());
        FileOutputStream outputstream = new FileOutputStream(outputFile);
        try {
            templateWorkbook.write(outputstream);
        } finally {
            outputstream.close();
        }
    }

    protected void fillGrades(List<Double> grades, HSSFSheet templateSheet, short columnIndex) {
        short rowIndex = skillRowStartIndex;
        for (Double grade : grades) {
            HSSFCell gradeCell = getOrCreateCell(templateSheet, rowIndex, columnIndex);
            setCellNumericValue(gradeCell, grade);
            rowIndex++;
        }
    }
}
